package org.basket.core;

import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.basket.xml.XMLSAX;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

/*
 * <db>
 *     <entity +kind +name/id ?parentKind ?parentName/parentId delete=delete>
 *          <property name type>value</property>
 */
public class DBImportSAX extends XMLSAX {

	private static final Logger log = Logger.getLogger(DBImportSAX.class.getName());

	Entity entity = null;
	String propertyName;
	String propertyType;
	boolean delete = false;

	public DBImportSAX(String xml, boolean ignoreWhitespace) {
		super(xml, ignoreWhitespace);
	}

	@Override
	public void endElement(String tag) {
		if ("entity".equals(tag)) {
			if (entity != null) {
				if (delete) {
					DBManager.ds.delete(entity.getKey());
				} else {
					DBManager.ds.put(entity);
				}
				entity = null;
			}
		} else if ("property".equals(tag)) {
			propertyName = null;
		}
	}

	@Override
	public void startElement(String tag, Map<String, String> attributes) {
		if ("entity".equals(tag)) {
			final String kind = attributes.get("kind");
			if (kind == null) {
				return;// no kind for the entity
			}

			final Key parentKey;
			final String parentKind = attributes.get("parentKind");
			if (parentKind != null) {
				final String parentName = attributes.get("parentName");
				Long parentId;
				try {
					parentId = Long.parseLong(attributes.get("parentId"));
				} catch (Exception e) {
					parentId = null;
				}
				if (parentId == null) {
					if (parentName == null) {
						parentKey = KeyFactory.createKey(parentKind, parentKind);
					} else {
						parentKey = KeyFactory.createKey(parentKind, parentName);
					}
				} else {
					if (parentName == null) {
						parentKey = KeyFactory.createKey(parentKind, parentId);
					} else {
						parentKey = KeyFactory.createKey(parentKind, parentName);
					}
				}
			} else {
				parentKey = null;
			}

			final Key key;
			{
				final String name = attributes.get("name");
				Long id;
				try {
					id = Long.parseLong(attributes.get("id"));
				} catch (Exception e) {
					id = null;
				}
				if (id == null) {
					if (name == null) {
						key = parentKey != null ? KeyFactory.createKey(parentKey, kind, kind) : KeyFactory.createKey(kind, kind);
					} else {
						key = parentKey != null ? KeyFactory.createKey(parentKey, kind, name) : KeyFactory.createKey(kind, name);
					}
				} else {
					if (name == null) {
						key = parentKey != null ? KeyFactory.createKey(parentKey, kind, id) : KeyFactory.createKey(kind, id);
					} else {
						key = parentKey != null ? KeyFactory.createKey(parentKey, kind, name) : KeyFactory.createKey(kind, name);
					}
				}
			}

			entity = new Entity(key);
			delete = "delete".equals(attributes.get("delete"));

		} else if ("property".equals(tag)) {
			propertyName = attributes.get("name");
			propertyType = attributes.get("type");
		}

	}

	@SuppressWarnings("unchecked")
	@Override
	public void text(String text) {
		if (entity == null || propertyName == null || propertyName.length() <= 0 || text == null || text.length() <= 0) {
			return;
		}
		Object value;
		try {
			Class clazz = Class.forName(propertyType);
			Constructor constructor = clazz.getConstructor(String.class);
			value = constructor.newInstance(text);
			entity.setProperty(propertyName, value);
		} catch (Exception e) {
			e.printStackTrace();
			log.log(Level.SEVERE, "cannot find class for name [" + propertyType + "]", e);
		}
	}
}
